--- /dev/null
+unit options;\r
+\r
+{\r
+ Copyright (C) 2005 Olaf Klein, o.k.klein@t-online.de\r
+\r
+ This program is free software; you can redistribute it and/or modify\r
+ it under the terms of the GNU General Public License as published by\r
+ the Free Software Foundation; either version 2 of the License, or\r
+ (at your option) any later version.\r
+\r
+ This program is distributed in the hope that it will be useful,\r
+ but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
+ GNU General Public License for more details.\r
+\r
+ You should have received a copy of the GNU General Public License\r
+ along with this program; if not, write to the Free Software\r
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA\r
+}\r
+\r
+interface\r
+\r
+uses\r
+ TypInfo, gnugettext, gnugettextDx,\r
+ Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,\r
+ StdCtrls, ExtCtrls, ComCtrls, Buttons,\r
+ Common;\r
+\r
+type\r
+ TfrmOptions = class(TForm)\r
+ pnBottom: TPanel;\r
+ pnOptions: TPanel;\r
+ btnOK: TBitBtn;\r
+ btnCancel: TBitBtn;\r
+ btnHelp: TBitBtn;\r
+ mmWarning: TMemo;\r
+ procedure CheckBoxClicked(Sender: TObject);\r
+ procedure FormCreate(Sender: TObject);\r
+ procedure btnHelpClick(Sender: TObject);\r
+ procedure FormKeyDown(Sender: TObject; var Key: Word;\r
+ Shift: TShiftState);\r
+ private\r
+ { Private declarations }\r
+ FOpts: TStringList;\r
+ FCanvas: TCanvas;\r
+ FInitialOpts: string;\r
+ procedure CreateStringOption(const x, y, tag: Integer; o: POption; xmax: Integer = -1);\r
+ procedure CreateIntegerOption(const x, y, tag: Integer; o: POption; xmax: Integer = -1);\r
+ procedure CreateFileOption(const x, y, tag: Integer; o: POption; IsInput: Boolean; xmax: Integer = -1);\r
+ function FindUpDown(AControl: TControl): TUpDown;\r
+ function GetOptsStr: string;\r
+ procedure OptionOpenFile(Sender: TObject);\r
+ procedure OptionSaveFile(Sender: TObject);\r
+ function ParseOptsLine(const Line: string; List: TStrings): Integer;\r
+ procedure SetOpts(AList: TStringList);\r
+ procedure SetOptsStr(const AValue: string);\r
+ public\r
+ { Public declarations }\r
+ FFormat: string;\r
+ FIsInput: Boolean;\r
+ constructor Create(AOwner: TComponent); override;\r
+ property\r
+ Opts: TStringList read FOpts write SetOpts;\r
+ property OptsStr: string read GetOptsStr write SetOptsStr;\r
+ end;\r
+\r
+type\r
+ eUnknownOption = class(Exception);\r
+ eParserError = class(Exception);\r
+ \r
+var\r
+ frmOptions: TfrmOptions;\r
+\r
+implementation\r
+\r
+uses\r
+ utils, main;\r
+\r
+{$R *.DFM}\r
+\r
+constructor TfrmOptions.Create(AOwner: TComponent); // override;\r
+begin\r
+ inherited Create(AOwner);\r
+ TranslateComponent(Self);\r
+ FCanvas := Main.frmMain.stbMain.Canvas;\r
+ mmWarning.Lines.Add(_('Be aware, that most options are made for the output side. '));\r
+ mmWarning.Lines.Add(_('Currently we don''t have a flag which tells us which direction is used the options.'));\r
+end;\r
+\r
+procedure TfrmOptions.SetOpts(AList: TStringList);\r
+var\r
+ i, j: Integer;\r
+ c: TComponent;\r
+ wc: TControl;\r
+ o: POption;\r
+ chb: TCheckBox;\r
+ xy: TPoint;\r
+ xmax: Integer;\r
+ lb: TLabel;\r
+begin\r
+ FOpts := AList;\r
+\r
+ xy.x := 0;\r
+ xy.y := 8;\r
+ xmax := 0;\r
+\r
+ for i := 0 to FOpts.Count - 1 do\r
+ begin\r
+ o := Pointer(FOpts.Objects[i]);\r
+ o.chb := nil;\r
+ o.edit := nil;\r
+\r
+ if (FFormat = '') then\r
+ begin\r
+ FFormat := o.format;\r
+ btnHelp.Hint := 'http://www.gpsbabel.org/readme.html#' + FFormat;\r
+ btnHelp.ShowHint := True;\r
+ end;\r
+\r
+ if FIsInput and (\r
+ (AnsiPos('generate ', o.hint) <> 0) or\r
+ (AnsiPos(' generate', o.hint) <> 0) or\r
+ (AnsiPos('output ', o.hint) <> 0) or\r
+ (AnsiPos(' output', o.hint) <> 0) or\r
+ (AnsiPos('write', o.hint) <> 0) or\r
+ (AnsiPos(' write', o.hint) <> 0)) then Continue;\r
+\r
+ chb := TCheckBox.Create(nil);\r
+ o.chb := chb;\r
+ chb.Name := '___' + o.name;\r
+ chb.OnClick := CheckBoxClicked;\r
+ chb.Tag := i + 1;\r
+\r
+ InsertComponent(chb);\r
+\r
+ chb.ParentFont := False;\r
+ chb.Font := Main.frmMain.stbMain.Font;\r
+ chb.Left := 8;\r
+ chb.Top := xy.y;\r
+ chb.Caption := dgettext('Options', o.Hint);\r
+ chb.Alignment := taRightJustify;\r
+ chb.Checked := False;\r
+ chb.Parent := pnOptions;\r
+\r
+ chb.Hint := SysUtils.Format(_('Short "%s"'), [o.name]);\r
+ chb.ShowHint := True;\r
+ chb.Width := 21 + Trunc(FCanvas.TextWidth(chb.Caption) * 1.25);\r
+\r
+ xy.y := xy.y + chb.Height + 8;\r
+ if (o.otype <> 4) then\r
+ if (chb.Width > xy.x) then xy.x := chb.Width;\r
+ if (chb.Width > xy.x) then\r
+ xmax := chb.Width;\r
+ end;\r
+\r
+ xy.y := 8;\r
+ xy.X := xy.X + 8;\r
+ if (xy.X < 42) then xy.X := 42;\r
+\r
+ for i := 0 to FOpts.Count - 1 do\r
+ begin\r
+ o := Pointer(FOpts.Objects[i]);\r
+ o.edit := nil;\r
+ \r
+ if (o.chb = nil) then Continue;\r
+\r
+ // ('unknown', 'integer', 'float', 'string', 'boolean', 'file', 'outfile');\r
+ case o.otype of\r
+ 1: CreateIntegerOption(xy.X, xy.Y - 2, i + 1, o, xmax);\r
+ 2, 3: CreateStringOption(xy.X, xy.Y - 2, i + 1, o, xmax);\r
+ 4: ;\r
+ 5: if FIsInput then CreateFileOption(xy.X, xy.Y - 2, i + 1, o, True, xmax);\r
+ 6: if not FIsInput then CreateFileOption(xy.X, xy.Y - 2, i + 1, o, False, xmax);\r
+ end;\r
+ if (o.edit <> nil) then\r
+ o.edit.Enabled := False;\r
+ xy.y := xy.y + chb.Height + 8;\r
+ end;\r
+\r
+ xy.X := 0;\r
+ xy.Y := 0;\r
+\r
+ for i := 0 to ComponentCount - 1 do\r
+ begin\r
+ c := Components[i];\r
+ if not c.InheritsFrom(TControl) then Continue;\r
+ if (c is TPanel) then Continue;\r
+ wc := Pointer(c);\r
+ if (wc.Parent <> pnOptions) then Continue;\r
+\r
+ j := wc.Left + wc.Width;\r
+ if (j > xy.X) then xy.X := j;\r
+ j := wc.Top + wc.Height;\r
+ if (j > xy.Y) then xy.Y := j;\r
+ if ( wc.Name = '' ) then Continue;\r
+ end;\r
+\r
+ Self.Width := xy.X + 8 + (Self.Width - Self.ClientWidth);\r
+ Self.Height := xy.Y + 8 +\r
+ mmWarning.Height + + pnBottom.Height +\r
+ (Self.Height - Self.ClientHeight);\r
+\r
+ i := btnCancel.Left - btnOK.Left;\r
+ btnCancel.Left := pnBottom.Width - btnCancel.Width - btnHelp.Left;\r
+ btnOK.Left := btnCancel.Left - i;\r
+end;\r
+\r
+function TfrmOptions.GetOptsStr: string;\r
+var\r
+ i: Integer;\r
+ o: POption;\r
+ c: TComponent;\r
+ s: string;\r
+begin\r
+ Result := '';\r
+ for i := 0 to FOpts.Count - 1 do\r
+ begin\r
+ o := Pointer(FOpts.Objects[i]);\r
+ if (o.chb = nil) or not(o.chb.Checked) then Continue;\r
+ if (Result <> '') then\r
+ Result := Result + ',';\r
+ Result := Result + o.name;\r
+ if (o.edit = nil) then Continue;\r
+ s := GetStrProp(o.edit, 'Text');\r
+ if (Pos(' ', s) <> 0) or (Pos('"', s) <> 0) or (Pos(',', s) <> 0) then\r
+ s := SysUtils.AnsiQuotedStr(s, '"');\r
+ Result := SysUtils.Format('%s=%s', [Result, s]);\r
+ end;\r
+end;\r
+\r
+procedure TfrmOptions.SetOptsStr(const AValue: string);\r
+var\r
+ l: TStrings;\r
+ i, j: Integer;\r
+ s, name, value: string;\r
+ o: POption;\r
+ ud: TUpDown;\r
+begin\r
+ l := TStringList.Create;\r
+ try\r
+\r
+ try\r
+ ParseOptsLine(AValue, l);\r
+ except\r
+ on E: exception do\r
+ raise eParserError.Create(_('Invalid line format!'));\r
+ end;\r
+\r
+ for i := 0 to l.Count - 1 do\r
+ begin\r
+ s := l.Strings[i];\r
+ j := Pos('=', s);\r
+ if (j > 0) then\r
+ begin\r
+ name := Copy(s, 1, j - 1);\r
+ value := Copy(s, j + 1, Length(s) - j);\r
+ end\r
+ else\r
+ begin\r
+ Name := s;\r
+ Value := '';\r
+ end;\r
+ if (name = '') then Continue;\r
+\r
+ j := FOpts.IndexOf(name);\r
+ if (j < 0) then\r
+ raise eUnknownOption.CreateFmt(_('Unknown option "%s"!'), [name]);\r
+\r
+ o := Pointer(FOpts.Objects[j]);\r
+ if (o.edit <> nil) then\r
+ begin\r
+ o.chb.Checked := True;\r
+ ud := FindUpDown(o.Edit);\r
+ if (ud <> nil) then\r
+ ud.Position := StrToInt(Value)\r
+ else\r
+ SetStrProp(o.edit, 'Text', Value);\r
+ end\r
+ else if (o.otype = 4) then\r
+ o.chb.Checked := (value = '') or (value <> '0');\r
+ end;\r
+ finally\r
+ l.Free;\r
+ end;\r
+ FInitialOpts := GetOptsStr;\r
+end;\r
+\r
+procedure TfrmOptions.CheckBoxClicked(Sender: TObject);\r
+var\r
+ i: Integer;\r
+ c: TComponent;\r
+ chb: TCheckBox;\r
+ ctrl: TWinControl;\r
+begin\r
+ if (Sender = nil) or not (Sender is TCheckBox) then Exit;\r
+ chb := Pointer(Sender);\r
+\r
+ for i := 0 to ComponentCount - 1 do\r
+ begin\r
+ c := Components[i];\r
+ if (c = chb) or not(c.InheritsFrom(TWinControl)) then Continue;\r
+ if (c.Tag <> chb.Tag) then Continue;\r
+ ctrl := Pointer(c);\r
+ ctrl.Enabled := chb.Checked;\r
+ end;\r
+end;\r
+\r
+procedure TfrmOptions.CreateStringOption(const x, y, tag: Integer; o: POption; xmax: Integer);\r
+var\r
+ ed: TEdit;\r
+begin\r
+ ed := TEdit.Create(Self);\r
+ o.edit := ed;\r
+\r
+ ed.Left := x;\r
+ ed.Top := y;\r
+ ed.Tag := tag;\r
+ ed.Parent := pnOptions;\r
+\r
+ if (o.def <> nil) then\r
+ ed.Text := string(o.def);\r
+end;\r
+\r
+procedure TfrmOptions.CreateIntegerOption(const x, y, tag: Integer; o: POption; xmax: Integer);\r
+var\r
+ ed: TEdit;\r
+ cb: TComboBox;\r
+ up: TUpDown;\r
+ i: Integer;\r
+begin\r
+ if (o.min <> nil) and (o.max <> nil) and\r
+ ((StrToInt(o.max) - StrToInt(o.min)) < 32) then\r
+ begin\r
+ cb := TComboBox.Create(Self);\r
+ o.edit := cb;\r
+ cb.Left := x;\r
+ cb.Top := y;\r
+ cb.Tag := tag;\r
+ if (cb.Left + cb.Width < xmax) then\r
+ cb.Left := xmax - cb.Width;\r
+ cb.Parent := pnOptions;\r
+\r
+ for i := StrToInt(o.min) to StrToInt(o.max) do\r
+ cb.Items.Add(IntToStr(i));\r
+ if (o.def <> nil) then\r
+ cb.Text := o.def\r
+ else\r
+ cb.ItemIndex := 0;\r
+ Exit;\r
+ end;\r
+\r
+ ed := TEdit.Create(Self);\r
+ o.edit := ed;\r
+\r
+ ed.Left := x;\r
+ ed.Top := y;\r
+ ed.Tag := tag;\r
+ ed.Parent := pnOptions;\r
+\r
+ up := TUpDown.Create(Self);\r
+ up.Parent := pnOptions;\r
+\r
+ ed.Width := ed.Width - up.Width;\r
+ up.Left := ed.Left + ed.Width;\r
+ up.Top := ed.Top;\r
+ if (o.min <> nil) then\r
+ up.Min := StrToInt(o.min)\r
+ else\r
+ up.Min := -(MAXSHORT-1);\r
+ if (o.max <> nil) then\r
+ up.Max := StrToInt(o.max)\r
+ else\r
+ up.Max := MAXSHORT;\r
+ if (o.def <> nil) then\r
+ up.Position := StrToInt(o.def);\r
+ up.Associate := ed;\r
+end;\r
+\r
+procedure TfrmOptions.FormCreate(Sender: TObject);\r
+begin\r
+ TranslateComponent(Self);\r
+end;\r
+\r
+procedure TfrmOptions.btnHelpClick(Sender: TObject);\r
+begin\r
+ WinOpenFile('http://www.gpsbabel.org/readme.html#' + FFormat);\r
+end;\r
+\r
+procedure TfrmOptions.CreateFileOption(const x, y, tag: Integer; o: POption; IsInput: Boolean; xmax: Integer = -1);\r
+var\r
+ ed: TEdit;\r
+ btn: TSpeedButton;\r
+begin\r
+ ed := TEdit.Create(Self);\r
+ o.edit := ed;\r
+\r
+ ed.Left := x;\r
+ ed.Top := y;\r
+ ed.Tag := tag;\r
+ ed.Parent := pnOptions;\r
+\r
+ btn := TSpeedButton.Create(Self);\r
+ btn.Parent := pnOptions;\r
+ btn.Tag := tag;\r
+ ed.Width := ed.Width - btn.Width;\r
+ btn.Left := ed.Left + ed.Width;\r
+ btn.Top := ed.top;\r
+\r
+ if IsInput then\r
+ begin\r
+ btn.OnClick := Self.OptionOpenFile;\r
+ frmMain.ImageList1.GetBitmap(15, btn.Glyph);\r
+ end\r
+ else\r
+ begin\r
+ btn.OnClick := Self.OptionSaveFile;\r
+ frmMain.ImageList1.GetBitmap(17, btn.Glyph);\r
+ end;\r
+end;\r
+\r
+procedure TfrmOptions.OptionOpenFile(Sender: TObject);\r
+var\r
+ c: TControl;\r
+ i: Integer;\r
+ o: POption;\r
+ d: TOpenDialog;\r
+begin\r
+ if (Sender = nil) or not(Sender is TControl) then Exit;\r
+\r
+ c := Pointer(Sender);\r
+\r
+ for i := 0 to FOpts.Count - 1 do\r
+ begin\r
+ o := Pointer(FOpts.Objects[i]);\r
+ if (o.chb = nil) or (o.chb.Tag <> c.Tag) then Continue;\r
+\r
+ d := TOpenDialog.Create(Self);\r
+ try\r
+ d.FileName := GetStrProp(o.edit, 'Text');\r
+ if d.Execute then\r
+ SetStrProp(o.edit, 'Text', d.FileName);\r
+ finally\r
+ d.Free;\r
+ end;\r
+ end;\r
+end;\r
+\r
+procedure TfrmOptions.OptionSaveFile(Sender: TObject);\r
+var\r
+ c: TControl;\r
+ i: Integer;\r
+ o: POption;\r
+ d: TSaveDialog;\r
+begin\r
+ if (Sender = nil) or not(Sender is TControl) then Exit;\r
+ \r
+ c := Pointer(Sender);\r
+\r
+ for i := 0 to FOpts.Count - 1 do\r
+ begin\r
+ o := Pointer(FOpts.Objects[i]);\r
+ if (o.chb = nil) or (o.chb.Tag <> c.Tag) then Continue;\r
+\r
+ d := TSaveDialog.Create(Self);\r
+ try\r
+ d.FileName := GetStrProp(o.edit, 'Text');\r
+ if d.Execute then\r
+ SetStrProp(o.edit, 'Text', d.FileName);\r
+ finally\r
+ d.Free;\r
+ end;\r
+ end;\r
+end;\r
+\r
+function TfrmOptions.ParseOptsLine(const Line: string; List: TStrings): Integer;\r
+var\r
+ s, name, val: string;\r
+ cin, cend: PChar;\r
+ c1, c2: PChar;\r
+ ins: Boolean;\r
+begin\r
+ List.Clear;\r
+ s := Trim(line) + ',';\r
+\r
+ cin := PChar(s);\r
+ cend := cin + StrLen(cin);\r
+\r
+ while (cin < cend) do\r
+ begin\r
+ c1 := StrScan(cin, '=');\r
+ c2 := StrScan(cin, ',');\r
+ if (c1 > c2) then c1 := nil;\r
+\r
+ if (c1 <> nil) then\r
+ begin\r
+ c1^ := #0;\r
+ name := string(cin);\r
+ val := '';\r
+\r
+ c1 := c1 + 1;\r
+ while (c1^ > #0) and (c1^ <= ' ') do c1 := c1 + 1;\r
+\r
+ if (c1^ = '"') then // dequote\r
+ begin\r
+ while (c1 < cend) do\r
+ begin\r
+ c1 := c1 + 1;\r
+ if (c1^ = '"') then\r
+ begin\r
+ if ((c1+1)^ = '"') then\r
+ c1 := c1 + 1\r
+ else\r
+ Break;\r
+ end;\r
+ val := val + c1^;\r
+ end;\r
+ c2 := StrScan(c1 + 1, ',');\r
+ end\r
+ else\r
+ begin\r
+ c2^ := #0;\r
+ val := string(c1);\r
+ end;\r
+ end\r
+ else\r
+ begin\r
+ c2^ := #0;\r
+ name := string(cin);\r
+ end;\r
+\r
+ if (name <> '') then\r
+ begin\r
+ if (val <> '') then\r
+ list.Add(Format('%s=%s', [name, val]))\r
+ else\r
+ list.Add(name);\r
+ end;\r
+\r
+ if (c2 = nil) then\r
+ Break\r
+ else\r
+ cin := c2 + 1;\r
+ end;\r
+\r
+ Result := List.Count;\r
+end;\r
+\r
+function TfrmOptions.FindUpDown(AControl: TControl): TUpDown;\r
+var\r
+ i: Integer;\r
+ c: TComponent;\r
+begin\r
+ Result := nil;\r
+ for i := 0 to ComponentCount - 1 do\r
+ begin\r
+ c := Components[i];\r
+ if c.InheritsFrom(TUpDown) and (TUpDown(c).Associate = AControl) then\r
+ begin\r
+ Result := Pointer(c);\r
+ Exit;\r
+ end;\r
+ end;\r
+end;\r
+\r
+procedure TfrmOptions.FormKeyDown(Sender: TObject; var Key: Word;\r
+ Shift: TShiftState);\r
+var\r
+ str: string;\r
+begin\r
+ if (Key <> 27) then Exit;\r
+\r
+ str := GetOptsStr;\r
+ if (str <> FInitialOpts) then\r
+ begin\r
+ if not(MessageDlg(_('Discard changes?'), mtWarning, mbOKCancel, 0) = mrOK) then\r
+ Exit; \r
+ end;\r
+ ModalResult := mrCancel;\r
+end;\r
+\r
+end.\r